// runs as a server on the client
// "/" returns the html view of the awwwe browser
// URLs have the following structure
// "/package/object/method
// "/auralvm/" aural view model package which returns json conversations
package main

import (
	"fmt"
	"net/http"

	"code.google.com/awwwe-browser/auralvm"
	"code.google.com/awwwe-browser/auralvm/bookmark"
	"code.google.com/awwwe-browser/auralvm/browser"
	"code.google.com/awwwe-browser/auralvm/feed"
	"code.google.com/awwwe-browser/auralvm/param"
	"code.google.com/awwwe-browser/auralvm/setting"
	"code.google.com/awwwe-browser/auralvm/tab"
	"code.google.com/awwwe-browser/auralvm/voisfile"
	"code.google.com/awwwe-browser/data"
	"code.google.com/awwwe-browser/issues"
	"code.google.com/awwwe-browser/voisedit/editvois"
)

const (
	Scheme        string = "http"
	Host          string = "localhost"
	Port          int    = 9999
	PRIV_KEY      string = "./certs/localhost.key"
	PUBLIC_KEY    string = "./certs/localhost.crt"
	VMPackage     string = "auralvm"
	EditorPackage string = "ve"
)

func main() {
	var err error
	// set continuers
	bookmark.StopContinuer = ContinueOnStop
	browser.StopContinuer = ContinueOnStop
	feed.StopContinuer = ContinueOnStop
	setting.StopContinuer = ContinueOnStop
	tab.StopContinuer = ContinueOnStop
	voisfile.StopContinuer = ContinueOnStop
	// set continuers
	bookmark.NextContinuer = FinalContinueOn
	browser.NextContinuer = FinalContinueOn
	feed.NextContinuer = FinalContinueOn
	setting.NextContinuer = FinalContinueOn
	tab.NextContinuer = FinalContinueOn
	voisfile.NextContinuer = FinalContinueOn
	// aural browser view model
	param.SetSchemeHostPortPackage(Scheme, Host, Port, VMPackage)
	// browsers
	http.HandleFunc("/test", auralvm.HandlerStartTestBrowser)
	http.HandleFunc("/awwwe", auralvm.HandlerStartAWWWEBrowser)
	// aural browser view models
	// aural browser browser tools
	http.HandleFunc(fmt.Sprintf("/%s/", param.Package), browser.HandlerBrowserListTools)
	http.HandleFunc(fmt.Sprintf("/%s/browser/listtools", param.Package), browser.HandlerBrowserListTools)
	http.HandleFunc(fmt.Sprintf("/%s/browser/quit", param.Package), browser.HandlerBrowserQuit)
	// aural browser bookmarks
	http.HandleFunc(fmt.Sprintf("/%s/bookmark/listtools", param.Package), bookmark.HandlerBookmarkListTools)
	http.HandleFunc(fmt.Sprintf("/%s/bookmark/listtolisten", param.Package), bookmark.HandlerBookmarkListToListen)
	http.HandleFunc(fmt.Sprintf("/%s/bookmark/listtoremove", param.Package), bookmark.HandlerBookmarkListToRemove)
	http.HandleFunc(fmt.Sprintf("/%s/bookmark/remove", param.Package), bookmark.HandlerBookmarkRemove)
	http.HandleFunc(fmt.Sprintf("/%s/bookmark/add", param.Package), bookmark.HandlerBookmarkAdd)
	// aural browser tabs
	http.HandleFunc(fmt.Sprintf("/%s/tab/listtools", param.Package), tab.HandlerTabListTools)
	http.HandleFunc(fmt.Sprintf("/%s/tab/replace", param.Package), tab.HandlerTabReplace)
	http.HandleFunc(fmt.Sprintf("/%s/tab/opennew", param.Package), tab.HandlerTabOpenNew)
	http.HandleFunc(fmt.Sprintf("/%s/tab/listtobookmark", param.Package), tab.HandlerTabListToBookmark)
	http.HandleFunc(fmt.Sprintf("/%s/tab/listtoclose", param.Package), tab.HandlerTabListToClose)
	http.HandleFunc(fmt.Sprintf("/%s/tab/close", param.Package), tab.HandlerTabClose)
	http.HandleFunc(fmt.Sprintf("/%s/tab/listtolisten", param.Package), tab.HandlerTabListToListen)
	http.HandleFunc(fmt.Sprintf("/%s/tab/listen", param.Package), tab.HandlerTabListen)
	http.HandleFunc(fmt.Sprintf("/%s/tab/submit", param.Package), tab.HandlerTabFormSubmit)
	// aural browser vois.xml files
	http.HandleFunc(fmt.Sprintf("/%s/vois/listtoopen", param.Package), voisfile.HandlerVoisListToOpen)
	http.HandleFunc(fmt.Sprintf("/%s/vois/save", param.Package), voisfile.HandlerVoisSave)
	// aural browser settings
	http.HandleFunc(fmt.Sprintf("/%s/settings/listtools", param.Package), setting.HandlerSettingsListTools)
	http.HandleFunc(fmt.Sprintf("/%s/settings/edithelp", param.Package), setting.HandlerSettingsHelpEdit)
	http.HandleFunc(fmt.Sprintf("/%s/settings/sethelp", param.Package), setting.HandlerSettingsHelpSave)
	// subscription feeds
	http.HandleFunc(fmt.Sprintf("/%s/feed/listtools", param.Package), feed.HandlerFeedListTools)
	http.HandleFunc(fmt.Sprintf("/%s/feed/listtolisten", param.Package), feed.HandlerFeedListToListen)
	http.HandleFunc(fmt.Sprintf("/%s/feed/listtoremove", param.Package), feed.HandlerFeedListToRemove)
	http.HandleFunc(fmt.Sprintf("/%s/feed/add", param.Package), feed.HandlerFeedAdd)
	http.HandleFunc(fmt.Sprintf("/%s/feed/remove", param.Package), feed.HandlerFeedRemove)
	// VOIS editor
	editvois.SetSchemeHostPortPackage(Scheme, Host, Port, EditorPackage)
	// VOIS editor html templates
	http.HandleFunc(fmt.Sprintf("/%s/", editvois.Package), editvois.HandlerDefault)
	http.HandleFunc(fmt.Sprintf("/%s/VoisEditor", editvois.Package), editvois.HandlerEditor)
	http.HandleFunc(fmt.Sprintf("/%s/VoisEditing", editvois.Package), editvois.HandlerEditing)

	http.HandleFunc(fmt.Sprintf("/%s/TrueKiss", editvois.Package), editvois.HandlerTrueKiss)
	http.HandleFunc(fmt.Sprintf("/%s/VoisHowTo/VoisLessons", editvois.Package), editvois.HandlerHowToLessons)
	http.HandleFunc(fmt.Sprintf("/%s/VoisHowTo/VoisIntro", editvois.Package), editvois.HandlerHowToIntro)
	http.HandleFunc(fmt.Sprintf("/%s/VoisHowTo/XpathIntro", editvois.Package), editvois.HandlerHowToXpathIntro)
	http.HandleFunc(fmt.Sprintf("/%s/VoisHowTo/ArticleSpaces", editvois.Package), editvois.HandlerHowToArticle)
	http.HandleFunc(fmt.Sprintf("/%s/VoisHowTo/NavigationSpaces", editvois.Package), editvois.HandlerHowToNavigation)
	http.HandleFunc(fmt.Sprintf("/%s/VoisHowTo/FormSpaces", editvois.Package), editvois.HandlerHowToForm)
	// VOIS editor css templates
	http.HandleFunc(fmt.Sprintf("/%s/Styles/Home", editvois.Package), editvois.HandlerHomeCSS)
	http.HandleFunc(fmt.Sprintf("/%s/Styles/NotHome", editvois.Package), editvois.HandlerNotHomeCSS)
	http.HandleFunc(fmt.Sprintf("/%s/Styles/General", editvois.Package), editvois.HandlerGeneralCSS)
	http.HandleFunc(fmt.Sprintf("/%s/Styles/Navigation", editvois.Package), editvois.HandlerNavigationCSS)
	http.HandleFunc(fmt.Sprintf("/%s/Styles/Form", editvois.Package), editvois.HandlerFormCSS)
	// VOIS editor files
	http.Handle("/vois.xml", http.FileServer(http.Dir(".")))
	http.Handle(fmt.Sprintf("/%s/Images/", editvois.Package), http.FileServer(http.Dir(".")))
	http.Handle(fmt.Sprintf("/%s/Javascript/", editvois.Package), http.FileServer(http.Dir(".")))
	http.Handle(fmt.Sprintf("/%s/Styles/VOISEditor.css", editvois.Package), http.FileServer(http.Dir(".")))
	// webspeechcodelab
	http.Handle("/webspeechcodelab/", http.FileServer(http.Dir(".")))
	// server
	if Scheme == "http" {
		http.ListenAndServe(param.HostPort(), nil)
	} else {
		err = http.ListenAndServeTLS(param.HostPort(), PUBLIC_KEY, PRIV_KEY, nil)
		if err != nil {
			// fmt.Print(err.Error())
		}
	}
}

// continue to another conversation using the source params.
// using the souce params is a fall back for when fatal errors occur.
func FinalContinueOn(w http.ResponseWriter, r *http.Request, vxml string) {
	var sourceobject, sourcemethod string
	var sourcetabkey, sourcecontentindex, sourcecontentcontentindex, sourceoptionindex int
	var respondwithtext bool
	defer issues.LogFlush()
	//issues.Logger.Printf("vxml is %s", vxml)
	_, respondwithtext = r.PostForm[param.ParamResponsdWithText]
	if respondwithtext {
		// write a simple text message
		w.Write([]byte(vxml))
		return
	}
	// sourceobject, sourcemethod, sourcecontentindex
	sourceobject, sourcemethod, sourcetabkey, sourcecontentindex, sourcecontentcontentindex, sourceoptionindex = getSourceParams(r)
	//issues.Logger.Printf("sourceobject %s, sourcemethod %s, sourcetabkey %d, sourcecontentindex %d, sourcecontentcontentindex %d, sourceoptionindex %d", sourceobject, sourcemethod, sourcetabkey, sourcecontentindex, sourcecontentcontentindex, sourceoptionindex)
	if len(vxml) > 0 {
		sourceoptionindex = -1
	}
	if sourceobject == "bookmark" {
		if sourcemethod == "listtools" {
			bookmark.ContinuerBookmarkListTools(w, r, vxml, sourceoptionindex, false)
			return
		} else if sourcemethod == "listtoopen" {
			bookmark.ContinuerBookmarkListToListen(w, r, vxml, sourceoptionindex, false)
			return
		} else if sourcemethod == "listtoremove" {
			bookmark.ContinuerBookmarkListToRemove(w, r, vxml, sourceoptionindex, false)
			return
		}
	} else if sourceobject == "tab" {
		if sourcemethod == "listtolisten" {
			tab.ContinuerTabListToListen(w, r, vxml, sourceoptionindex, false)
		} else if sourcemethod == "listtobookmark" {
			tab.ContinuerTabListToBookmark(w, r, vxml, sourceoptionindex, false)
		} else if sourcemethod == "listtoclose" {
			tab.ContinuerTabListToClose(w, r, vxml, sourceoptionindex, false)
		} else if sourcemethod == "listen" {
			tab.ContinuerTabListen(w, r, vxml, sourcetabkey, sourcecontentindex, sourcecontentcontentindex, sourceoptionindex, false)
		} else { // if sourcemethod == "listtools"
			tab.ContinuerTabListTools(w, r, vxml, sourceoptionindex, false)
		}
		return
	} else if sourceobject == "vois" {
		if sourcemethod == "listtoopen" {
			voisfile.ContinuerVoisListToOpen(w, r, vxml, sourceoptionindex, false)
		} else { // if sourcemethod == "listtools"
			browser.ContinuerBrowserListTools(w, r, vxml, sourceoptionindex, false, false)
		}
		return
	} else if sourceobject == "settings" {
		//if sourcemethod == "listtools"
		setting.ContinuerSettingsListTools(w, r, vxml, sourceoptionindex, false)
		return
	} else if sourceobject == "browser" {
		//if sourcemethod == "listtools"
		browser.ContinuerBrowserListTools(w, r, vxml, sourceoptionindex, false, false)
		return
	} else if sourceobject == "html" {
		// write a simple html message
		w.Write([]byte("<html><head></head><body><p><b>"))
		w.Write([]byte(vxml))
		w.Write([]byte("</b></p></body></html>"))
		return
	} else {
		// default to browser list tools
		browser.ContinuerBrowserListTools(w, r, vxml, -1, false, false)
	}
}

// continue to another conversation using the source params.
// using the souce params is a fall back for when fatal errors occur.
func ContinueOnStop(w http.ResponseWriter, r *http.Request, vxml string) {
	var respondwithtext bool
	_, respondwithtext = r.PostForm[param.ParamResponsdWithText]
	if respondwithtext {
		// write a simple text message
		w.Write([]byte(vxml))
	} else {
		browser.ContinuerBrowserListTools(w, r, vxml, -1, false, false)
	}
}

// get the source params from the request.
func getSourceParams(r *http.Request) (string, string, int, int, int, int) {
	var object, method string
	var tabkey, contentindex, contentcontentindex, contentoptionindex int
	var values []string
	var ok bool
	// object
	values, ok = r.Form[param.ParamSourceObject]
	if ok && len(values) == 1 {
		object = values[0]
	} else {
		object = data.EmptyString
	}
	// method
	values, ok = r.Form[param.ParamSourceMethod]
	if ok && len(values) == 1 {
		method = values[0]
	} else {
		method = data.EmptyString
	}
	// tab key
	values, ok = r.Form[param.ParamSourceTabKey]
	if ok && len(values) == 1 {
		tabkey, ok = data.StringToInt(values[0])
		if !ok {
			tabkey = 0
		}
	} else {
		tabkey = 0
	}
	// content index ( content index or list index for tool lists )
	values, ok = r.Form[param.ParamSourceOptionIndex]
	if ok && len(values) == 1 {
		contentindex, ok = data.StringToInt(values[0])
		if !ok {
			contentindex = -1
		}
	} else {
		contentindex = -1
	}
	// content, content index
	values, ok = r.Form[param.ParamSourceContentContentIndex]
	if !ok || (ok && len(values) != 1) {
		contentcontentindex = 0
	} else {
		contentcontentindex, ok = data.StringToInt(values[0])
		if !ok {
			contentcontentindex = 0
		}
	}
	// content option index
	values, ok = r.Form[param.ParamSourceOptionIndex]
	if !ok || (ok && len(values) != 1) {
		contentoptionindex = -1
	} else {
		contentoptionindex, ok = data.StringToInt(values[0])
		if !ok {
			contentoptionindex = -1
		}
	}
	return object, method, tabkey, contentindex, contentcontentindex, contentoptionindex
}
